#ifndef __SYSTEMS__SCHEDULER__HPP__
# define __SYSTEMS__SCHEDULER__HPP__

# include "system.hpp"

# include <boost/asio/io_service.hpp>
# include <boost/asio/deadline_timer.hpp>
# include <boost/function.hpp>
# include <boost/thread.hpp>
# include <boost/shared_ptr.hpp>
# include <boost/noncopyable.hpp>

# include <vector>

typedef boost::function<void()> handler_t;

/**
 * @brief Realizes delayed jobs scheduler.
 * @remarks
 *      Contains number of worker threads which will
 *      perform jobs when them time came.
 */
class scheduler_t : private boost::noncopyable, public if_system_t
{
public:

    static boost::shared_ptr<if_system_t> create(f_engine_t *engine);

    /**
     * @brief Start scheduler with some workers count.
     */
    void start(); /*override*/
    void stop();

    /**
     * @brief Return workers io_service.
     * @remarks
     *    Useful to perform some jobs directly with io_service.
     */
    boost::asio::io_service &workers_svc();

    ~scheduler_t();

    /**
     * @brief Setup delayed job.
     * @param handler Describes job action which will be performed then time came.
     */
    void set_timer(handler_t handler, boost::posix_time::time_duration &time);

    /**
     * @brief Direct execute some job in workers threads.
     */
    void exec_by_worker(handler_t handler);

private:

    scheduler_t(f_engine_t *engine);

    /**
     * @brief Typically worker thread function.
     */
    void worker_thr_func(size_t num);

    /**
     * @brief Timer thread function.
     * @remarks
     *    Timer events passed to separate thread to guarantee
     *    execution time precision of delayed jobs when
     *    we have low worker threads count.
     */
    void timer_thr_func();

    /**
     * @brief Internal timer handler.
     */
    void timer_handler(boost::shared_ptr<boost::asio::deadline_timer> timer_holder, handler_t &handler, const boost::system::error_code& error);

    boost::asio::io_service worker_svc_;
    boost::asio::io_service timer_svc_;

    /// Workers thread pool
    std::vector<boost::shared_ptr<boost::thread> > workers_;

    /// Timer thread
    boost::thread timer_thr_;

    f_engine_t *engine_;
};

#endif //__SYSTEMS__SCHEDULER__HPP__
